/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2009>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using MyPhotoIndex.Controls.TagTree;
using MyPhotoIndex.DataAccess;
using MyPhotoIndex.Utilities.Types;
using MyPhotoIndex.Interfaces;
using MyPhotoIndex.ImageBank.Query;
using MyPhotoIndex.ImageBank;
using MyPhotoIndex.Controls;
using System.Threading;
using MyPhotoIndex.Settings;
using MyPhotoIndex.Utilities;
using MyPhotoIndex.Interfaces.Tagging;
using MyPhotoIndex.Interfaces.Imaging;

namespace MyPhotoIndex
{
    public partial class ComplexSearchForm : FormTemplate
    {
        private delegate void VoidMethodDelegate();
        private delegate Point PointMethodDelegate(Point point);

        private SelectedTagsCollection m_withAndTags = new SelectedTagsCollection();
        private SelectedTagsCollection m_withOrTags = new SelectedTagsCollection();
        private SelectedTagsCollection m_withoutTags = new SelectedTagsCollection();
        private MyPhotoIndexThumbnailViewer m_source;
        private ToolTip m_tooltip = new ToolTip();
        SavedQuery m_savedQuery;

        public ComplexSearchForm(SavedQuery savedQuery):
            this()
        {
            if (savedQuery == null)
            {
                throw new NullReferenceException("savedQuery");
            }

            m_savedQuery = savedQuery;
            this.Text += " " + m_savedQuery.Name;

            SavedQueryToForm();
        }

        public ComplexSearchForm()
        {
            InitializeComponent();

            withAndThumbnailViewer.ImageList = m_withAndTags;
            withAndThumbnailViewer.DragDrop += new DragEventHandler(withAndThumbnailViewer_DragDrop);
            withAndThumbnailViewer.DragOver += new DragEventHandler(withAndThumbnailViewer_DragOver);
            withAndThumbnailViewer.DragEnter += new DragEventHandler(withAndThumbnailViewer_DragEnter);
            withAndThumbnailViewer.DragLeave += new EventHandler(withAndThumbnailViewer_DragLeave);
            withAndThumbnailViewer.MouseDown += new MouseEventHandler(withAndThumbnailViewer_MouseDown);
            withAndThumbnailViewer.MouseMove += new MouseEventHandler(withAndThumbnailViewer_MouseMove);
            withAndThumbnailViewer.MouseLeave += new EventHandler(withAndThumbnailViewer_MouseLeave);
            withAndThumbnailViewer.ThumbnailMouseClickEvent += new EventHandler<ThumbnailMouseEventArgs>(thumbnailViewer_ThumbnailMouseClickEvent);

            withOrThumbnailViewer.ImageList = m_withOrTags;
            withOrThumbnailViewer.DragDrop += new DragEventHandler(withAndThumbnailViewer_DragDrop);
            withOrThumbnailViewer.DragOver += new DragEventHandler(withAndThumbnailViewer_DragOver);
            withOrThumbnailViewer.DragEnter += new DragEventHandler(withAndThumbnailViewer_DragEnter);
            withOrThumbnailViewer.DragLeave += new EventHandler(withAndThumbnailViewer_DragLeave);
            withOrThumbnailViewer.MouseDown += new MouseEventHandler(withAndThumbnailViewer_MouseDown);
            withOrThumbnailViewer.MouseMove += new MouseEventHandler(withAndThumbnailViewer_MouseMove);
            withOrThumbnailViewer.MouseLeave += new EventHandler(withAndThumbnailViewer_MouseLeave);
            withOrThumbnailViewer.ThumbnailMouseClickEvent += new EventHandler<ThumbnailMouseEventArgs>(thumbnailViewer_ThumbnailMouseClickEvent);

            withoutThumbnailViewer.ImageList = m_withoutTags;
            withoutThumbnailViewer.DragDrop += new DragEventHandler(withAndThumbnailViewer_DragDrop);
            withoutThumbnailViewer.DragOver += new DragEventHandler(withAndThumbnailViewer_DragOver);
            withoutThumbnailViewer.DragEnter += new DragEventHandler(withAndThumbnailViewer_DragEnter);
            withoutThumbnailViewer.DragLeave += new EventHandler(withAndThumbnailViewer_DragLeave);
            withoutThumbnailViewer.MouseDown += new MouseEventHandler(withAndThumbnailViewer_MouseDown);
            withoutThumbnailViewer.MouseMove += new MouseEventHandler(withAndThumbnailViewer_MouseMove);
            withoutThumbnailViewer.MouseLeave += new EventHandler(withAndThumbnailViewer_MouseLeave);
            withoutThumbnailViewer.ThumbnailMouseClickEvent += new EventHandler<ThumbnailMouseEventArgs>(thumbnailViewer_ThumbnailMouseClickEvent);

            relationComboBox.Items.Add(new TranslatedParameter(true, Resources.Resources.Relation_And));
            relationComboBox.Items.Add(new TranslatedParameter(false, Resources.Resources.Relation_Or));
            relationComboBox.SelectedIndex = 0;

            RemoveToolStripMenuItem.Click += new EventHandler(RemoveToolStripMenuItem_Click);
        }

        void RemoveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            List<int> removeList = new List<int>();
            ToolStripDropDownItem tsddi = sender as ToolStripDropDownItem;
            MyPhotoIndexThumbnailViewer viewer = tsddi.Owner.Tag as MyPhotoIndexThumbnailViewer;
            foreach (int selectedImageId in viewer.SelectedImages)
            {
                removeList.Add(selectedImageId);
            }

            foreach (int removeImageId in removeList)
            {
                viewer.ImageList.Remove(removeImageId);
            }

            viewer.Refresh();
        }

        void thumbnailViewer_ThumbnailMouseClickEvent(object sender, ThumbnailMouseEventArgs e)
        {
            if (e.MouseButton == MouseButtons.Right)
            {
                MyPhotoIndexThumbnailViewer thumbnailViewer = ((Thumbnail)sender).Parent;
                SelectedImagesContextMenu.Tag = thumbnailViewer;
                SelectedImagesContextMenu.Show(thumbnailViewer, e.X, e.Y);
            }
        }

        void withAndThumbnailViewer_MouseLeave(object sender, EventArgs e)
        {
            m_tooltip.Hide(this);
        }

        void withAndThumbnailViewer_MouseMove(object sender, MouseEventArgs e)
        {
            MyPhotoIndexThumbnailViewer viewer = sender as MyPhotoIndexThumbnailViewer;
            Thumbnail thumbnail = viewer.GetThumbnailFromPosition(Cursor.Position);
            if (thumbnail != null)
            {
                Point pos = this.PointToClient(Cursor.Position);
                pos.X += 5;
                m_tooltip.Show(ImageTagCollection.Instance[thumbnail.ImageData.Id].Path, this, pos);
            }
            else
            {
                m_tooltip.Hide(this);
            }
        }

        void withAndThumbnailViewer_MouseDown(object sender, MouseEventArgs e)
        {
            m_source = sender as MyPhotoIndexThumbnailViewer;
        }

        void withAndThumbnailViewer_DragLeave(object sender, EventArgs e)
        {
            MyPhotoIndexThumbnailViewer tv = sender as MyPhotoIndexThumbnailViewer;
            Win32Interop.ImageDragHelper.ImageList_DragLeave(tv.Handle);
        }

        void withAndThumbnailViewer_DragEnter(object sender, DragEventArgs e)
        {
            MyPhotoIndexThumbnailViewer tv = sender as MyPhotoIndexThumbnailViewer;
            Win32Interop.ImageDragHelper.ImageList_DragEnter(tv.Handle, e.X - tv.Left, e.Y - tv.Top);
        }

        void withAndThumbnailViewer_DragOver(object sender, DragEventArgs e)
        {
            MyPhotoIndexThumbnailViewer tv = sender as MyPhotoIndexThumbnailViewer;
            // Compute drag position and move image
            Point point = tv.PointToClient(new Point(e.X, e.Y));
            Win32Interop.ImageDragHelper.ImageList_DragMove(point.X, point.Y);

            TreeNode tn = (TreeNode)e.Data.GetData(typeof(TreeNode));
            Thumbnail thumbnail = null;
            if (tn == null)
            {
                thumbnail = (Thumbnail)e.Data.GetData(typeof(Thumbnail));
            }

            if (tn != null ||
                thumbnail != null)
            {
                e.Effect = DragDropEffects.Link;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        void withAndThumbnailViewer_DragDrop(object sender, DragEventArgs e)
        {
            TreeNode selectedtagNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
            Thumbnail thumbnail = null;
            if (selectedtagNode == null)
            {
                thumbnail = (Thumbnail)e.Data.GetData(typeof(Thumbnail));
            }

            if (selectedtagNode == null &&
                thumbnail == null)
            {
                return;
            }

            IImageTag tag = null;

            if (selectedtagNode != null)
            {
                tag = selectedtagNode.Tag as IImageTag;
            }
            else
            if (thumbnail != null)
            {
                tag = ImageTagCollection.Instance[thumbnail.ImageData.Id];
                if (m_source != null)
                {
                    SelectedTagsCollection collection = m_source.ImageList as SelectedTagsCollection;
                    collection.Remove(tag.Id);
                    m_source.Refresh();
                }
            }
           
            if (tag == null)
            {
                return;
            }

            MyPhotoIndexThumbnailViewer tv = sender as MyPhotoIndexThumbnailViewer;
            SelectedTagsCollection tagsCollection = tv.ImageList as SelectedTagsCollection;
            tagsCollection.Add(tag.Id);
            tv.Refresh();
        }

        private void AdvancedQuery_Load(object sender, EventArgs e)
        {

        }

        protected override void OkButton_Click(object sender, EventArgs e)
        {
            ExecuteQuery(sender, e);
        }

        private void ExecuteQuery(object sender, EventArgs e)
        {
            SavedQuery savedQuery = GetSavedQuery();
            List<int> filteredList = savedQuery.ExecuteQuery(false);
            Storage.Instance.Filter(filteredList);
        }

        protected override void SaveToolStripButton_Click(object sender, EventArgs e)
        {
            SavedQuery savedQuery = null;

            if (m_savedQuery == null)
            {
                SearchSaveForm ssf = new SearchSaveForm();
                ssf.QueryName = BuildQueryName();
                DialogResult result = ssf.ShowDialog(this);
                if (result == DialogResult.Cancel)
                {
                    return;
                }

                savedQuery = GetSavedQuery();
                savedQuery.Name = ssf.QueryName;
            }
            else
            {
                savedQuery = GetSavedQuery();

                m_savedQuery.WithAnd = savedQuery.WithAnd;
                m_savedQuery.WithOr = savedQuery.WithOr;
                m_savedQuery.Without = savedQuery.Without;
                m_savedQuery.Relation = savedQuery.Relation;

                savedQuery = m_savedQuery;
            }

            SavedQueriesCollection.Instance.Save(savedQuery);

            ((Main)this.Owner).BuildSavedQueriesMenu();
        }

        private SavedQuery GetSavedQuery()
        {
            SavedQuery savedQuery = new SavedQuery();

            int ii = 0;
            savedQuery.WithAnd = new int[m_withAndTags.Count];
            foreach (IImageData tag in m_withAndTags)
            {
                savedQuery.WithAnd[ii++] = tag.Id;
            }

            bool relation = (bool)((TranslatedParameter)relationComboBox.SelectedItem).Id;
            savedQuery.Relation = relation;

            ii = 0;
            savedQuery.WithOr = new int[m_withOrTags.Count];
            foreach (IImageData tag in m_withOrTags)
            {
                savedQuery.WithOr[ii++] = tag.Id;
            }

            ii = 0;
            savedQuery.Without = new int[m_withoutTags.Count];
            foreach (IImageData tag in m_withoutTags)
            {
                savedQuery.Without[ii++] = tag.Id;
            }

            return savedQuery;
        }

        private string BuildQueryName()
        {
            StringBuilder sb = new StringBuilder();

            bool isFirst = true;
            if (m_withAndTags.Count > 0)
            {
                sb.Append("(");
            }

            foreach (IImageData tag in m_withAndTags)
            {
                if (isFirst == false)
                {
                    sb.Append(" ");
                    sb.Append(Resources.Resources.Relation_And);
                    sb.Append(" ");
                }

                sb.Append(ImageTagCollection.Instance[tag.Id].Name);
                isFirst = false;
            }

            if (m_withAndTags.Count > 0)
            {
                sb.Append(")");
            }

            if (sb.Length > 0 &&
            m_withOrTags.Count > 0)
            {
                bool relation = (bool)((TranslatedParameter)relationComboBox.SelectedItem).Id;
                sb.Append(" ");
                sb.Append(relation ? Resources.Resources.Relation_And : Resources.Resources.Relation_Or);
                sb.Append(" ");
            }

            isFirst = true;
            if (m_withOrTags.Count > 0)
            {
                sb.Append("(");
            }

            foreach (IImageData tag in m_withOrTags)
            {
                if (isFirst == false)
                {
                    sb.Append(" ");
                    sb.Append(Resources.Resources.Relation_Or);
                    sb.Append(" ");
                }

                sb.Append(ImageTagCollection.Instance[tag.Id].Name);
                isFirst = false;
            }

            if (m_withOrTags.Count > 0)
            {
                sb.Append(")");
            }

            if (m_withoutTags.Count > 0)
            {
                sb.Append(" ");
                sb.Append(Resources.Resources.Relation_NotWith);
                sb.Append(" ");
            }

            isFirst = true;
            foreach (IImageData tag in m_withoutTags)
            {
                if (isFirst == false)
                {
                    sb.Append(" ");
                    sb.Append(Resources.Resources.Relation_And);
                    sb.Append(" ");
                }

                sb.Append(ImageTagCollection.Instance[tag.Id].Name);
                isFirst = false;
            }

            return sb.ToString();
        }

        private void SavedQueryToForm()
        {
            foreach(int tagId in m_savedQuery.WithAnd)
            {
                m_withAndTags.Add(tagId);
            }

            foreach (int tagId in m_savedQuery.WithOr)
            {
                m_withOrTags.Add(tagId);
            }

            foreach (int tagId in m_savedQuery.Without)
            {
                m_withoutTags.Add(tagId);
            }

            relationComboBox.SelectedIndex = m_savedQuery.Relation ? 0 : 1;

            withAndThumbnailViewer.Refresh();
            withoutThumbnailViewer.Refresh();
            withoutThumbnailViewer.Refresh();
        }
    }
}